package br.com.saeng2D.analiseLxSi;

import java.util.ArrayList;

import br.com.saeng2D.analiseLxSi.al.AnalisadorLexico;
import br.com.saeng2D.analiseLxSi.al.Estado;

public class ScannerLex {
	
	private ArrayList<String> expressao = new ArrayList<String>();
	private ArrayList<String> grupoTermo = new ArrayList<String>();
	

	public ScannerLex(String equacao) throws Exception{
		
		//String equacao = "V1 * 0 + 3598.24 * 19 + 4497.80 * 25 + 89 * 110 - (35 * 60) - (H5 * 10) - (V5 * 130) = 0";
		AnalisadorLexico al = new AnalisadorLexico(equacao, false); //separa os termos da expressão
		while (!al.analisado()) {
			al.reconhecerAtomico();
			Estado estado = al.estado;
			expressao.add(al.getCadeiaReconhecida());	
			grupoTermo.add(estado.grupo);
		}	
		for(int j =0;j<3;j++){
			compactarExpressao();
		}
		for(int j =0;j<3;j++){
			isolarNumeros();
		}
		for(int j =0;j<3;j++){
			compactarExpressao();
		}

	}
	
	public void compactarExpressao(){
		for(int i=0;i<expressao.size();i++){//compacta as multiplicações da expressao
			if(expressao.get(i).equals("*")){
				if(i==1&&grupoTermo.get(i-1)=="numero"){
					String produto = resolveMult(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
					expressao.remove(i-1);
					expressao.remove(i-1);
					expressao.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					expressao.add(i-1,produto);
					grupoTermo.add(i-1,"numero");
				}else if(i>1&&grupoTermo.get(i-1)=="numero"&& !expressao.get(i-2).equals("(")){
					String produto = resolveMult(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
					expressao.remove(i-1);
					expressao.remove(i-1);
					expressao.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					expressao.add(i-1,produto);
					grupoTermo.add(i-1,"numero");
				}else if(grupoTermo.get(i-1)=="numero"&& expressao.get(i-2).equals("(")){//resolve e tira os parenteses
					String produto = resolveMult(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
					expressao.remove(i-2);
					expressao.remove(i-2);
					expressao.remove(i-2);
					expressao.remove(i-2);
					expressao.remove(i-2);
					grupoTermo.remove(i-2);
					grupoTermo.remove(i-2);
					grupoTermo.remove(i-2);
					grupoTermo.remove(i-2);
					grupoTermo.remove(i-2);
					expressao.add(i-2,produto);
					grupoTermo.add(i-2,"numero");
				}
			}
		}
		//System.out.println("cp Mult "+expressao);
		for(int i=0;i<expressao.size();i++){//compacta as subtraçoes e tambem 
											//transforma os numeros em negativo quando tem um sinal negativo na frente
			if(i==0&&expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("numero")){ 
				String numNeg = expressao.get(i+1); 
				expressao.remove(i);
				expressao.remove(i);
				grupoTermo.remove(i);
				grupoTermo.remove(i);
				expressao.add(i, "-"+numNeg);
				grupoTermo.add(i,"numero");
			}else if(i==0&&expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("variavel")){
				expressao.remove(i);
				grupoTermo.remove(i);
				expressao.add(i+1,"-1");
				expressao.add(i+1,"*");
				grupoTermo.add(i+1,"numero");
				grupoTermo.add(i+1,"operador");
			}else if(i>0&&expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("variavel")){
				expressao.remove(i);
				grupoTermo.remove(i);
				expressao.add(i+1,"-1");
				expressao.add(i+1,"*");
				grupoTermo.add(i+1,"numero");
				grupoTermo.add(i+1,"operador");
				expressao.add(i, "+");
				grupoTermo.add(i,"operador");
			}else if(i==0 && expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("abre parentese")&&expressao.get(i+4).equals("0")){
				expressao.remove(i);
				expressao.remove(i);
				expressao.remove(i+3);
				grupoTermo.remove(i);
				grupoTermo.remove(i);
				grupoTermo.remove(i+4);
			}else if(i==0 && expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("abre parentese")&& !expressao.get(i+4).equals("0")){
				String numNeg = expressao.get(i+3);
				expressao.set(i+4,"-"+numNeg);
				expressao.remove(i);
				expressao.remove(i);
				expressao.remove(i+3);
				grupoTermo.remove(i);
				grupoTermo.remove(i);
				grupoTermo.remove(i+3);
			}else if(i>0 && expressao.get(i).equals("-")&& grupoTermo.get(i+1).equals("abre parentese")&& expressao.get(i+4).equals("0")){
				expressao.remove(i);
				expressao.remove(i);
				expressao.remove(i+3);
				grupoTermo.remove(i);
				grupoTermo.remove(i);
				grupoTermo.remove(i+3);
				expressao.add(i,"+");
				grupoTermo.add(i,"operador");
			}else if(i>0 && expressao.get(i).equals("-")&&grupoTermo.get(i+1).equals("abre parentese")&& !expressao.get(i+4).equals("0")){
				String numNeg = expressao.get(i+4);
				expressao.set(i+4,"-"+numNeg);
				expressao.remove(i);
				expressao.remove(i);
				expressao.remove(i+3);
				grupoTermo.remove(i);
				grupoTermo.remove(i);
				grupoTermo.remove(i+3);
				expressao.add(i,"+");
				grupoTermo.add(i,"operador");
			}else if(i>0&& expressao.get(i).equals("-")&& grupoTermo.get(i-1).equals("numero")&& grupoTermo.get(i+1).equals("numero")&& expressao.get(i-2).equals("-")){
				String result = resolveSubtr(Double.parseDouble("-"+expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
				expressao.remove(i-2);
				expressao.remove(i-2);
				expressao.remove(i-2);
				expressao.remove(i-2);
				grupoTermo.remove(i-2);
				grupoTermo.remove(i-2);
				grupoTermo.remove(i-2);
				grupoTermo.remove(i-2);
				expressao.add(i-2,result);
				expressao.add(i-2,"+");
				grupoTermo.add(i-2,"numero");
				grupoTermo.add(i-2,"operador");
			}else if(i>0&& expressao.get(i).equals("-")&& grupoTermo.get(i-1).equals("numero")&& grupoTermo.get(i+1).equals("numero")&& expressao.get(i-2).equals("+")){
				String result = resolveSubtr(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
				expressao.remove(i-1);
				expressao.remove(i-1);
				expressao.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				expressao.add(i-1,result);
				grupoTermo.add(i-1,"numero");
			}
		}
		//System.out.println("cp Subt "+expressao);
		for(int i=0;i<expressao.size();i++){
			if(i==1&& expressao.get(i).equals("+")&& grupoTermo.get(i-1)=="numero" && grupoTermo.get(i+1)=="numero" ){
				String result = resolveSoma(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
				expressao.remove(i-1);
				expressao.remove(i-1);
				expressao.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				expressao.add(i-1,result);
				grupoTermo.add(i-1,"numero");
			}
			if(i>1 && expressao.get(i).equals("+")&& grupoTermo.get(i-1)=="numero" && grupoTermo.get(i+1)=="numero" && !expressao.get(i-2).equals("*")){
				String result = resolveSoma(Double.parseDouble(expressao.get(i-1)), Double.parseDouble(expressao.get(i+1)));
				expressao.remove(i-1);
				expressao.remove(i-1);
				expressao.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				grupoTermo.remove(i-1);
				expressao.add(i-1,result);
				grupoTermo.add(i-1,"numero");
			}
		}
		//System.out.println("cp Som "+expressao);
	}
	
	public void isolarNumeros(){
		String num = new String();
		isolador :for(int i=0;i<expressao.size();i++){
			if(!expressao.get(i).equals("=")){
				if(grupoTermo.get(i)=="numero"&& i==0){ 
					num=expressao.get(i);
					expressao.remove(i);
					grupoTermo.remove(i);
					/*expressao.remove(expressao.size()-1);
					grupoTermo.remove(grupoTermo.size()-1);*/
					expressao.add("+");
					double temp = Double.parseDouble(num)*(-1.0);
					expressao.add(Double.toString(temp));
					grupoTermo.add("operador");	
					grupoTermo.add("numero");	
				}else if(grupoTermo.get(i)=="numero"&& expressao.get(i-1).equals("+")&&i>0){
					num=expressao.get(i);
					expressao.remove(i-1);
					expressao.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					/*expressao.remove(expressao.size()-1);
					grupoTermo.remove(grupoTermo.size()-1);*/
					expressao.add("+");
					double temp = Double.parseDouble(num)*(-1.0);
					expressao.add(Double.toString(temp));
					grupoTermo.add("operador");	
					grupoTermo.add("numero");
				}else if(grupoTermo.get(i)=="numero"&& expressao.get(i-1).equals("-")&&i>0){
					num=expressao.get(i);
					expressao.remove(i-1);
					expressao.remove(i-1);
					grupoTermo.remove(i-1);
					grupoTermo.remove(i-1);
					/*expressao.remove(expressao.size()-1);
					grupoTermo.remove(grupoTermo.size()-1);*/
					expressao.add("+");
					expressao.add(Double.toString(Double.parseDouble(num)));
					grupoTermo.add("operador");	
					grupoTermo.add("numero");
				}
			}else{
				break isolador;
			}
			
			
		}		
	}
	
	
	public ArrayList<String> retornaExpressao(){ 	
		return expressao;
	}
	public ArrayList<String> retornaGrupoTermo(){		
		return grupoTermo;
	}	
	
	private String resolveSubtr(double termo1, double termo2) {
		String result = Double.toString(termo1-termo2);
		return result;
	}
	private String resolveMult(double fator1, double fator2){
		String result = Double.toString(fator1*fator2);		
		return result;
	}	
	private String resolveSoma(double termo1,double termo2){
		String result = Double.toString(termo1+termo2);
		return result;
	}
	
	
	
	
	
	

}
